//author:kakake
class tsfrontService {
    public data = {
        dbConn: TSLobsterAPI.Program.GetDbConn(),
        WorkId: 1
    }

    constructor(workid: number) {
        this.data.WorkId = workid;
    }

    /**
     * 生成订单号OrderNo
     */
    generateTimeReqestNumber() {
        var date = new Date();
        return date.getFullYear().toString() + this.pad2(date.getMonth() + 1) + this.pad2(date.getDate()) + this.pad2(date.getHours()) + this.pad2(date.getMinutes()) + this.pad2(date.getSeconds()) + Math.random().toFixed(6).slice(-6);
    }

    pad2(n) { return n < 10 ? '0' + n : n + '' }
}

interface Pay_Order_Model {
    "ID": number,
    "SubMchId": string,
    "BusinessOrderNo": string,
    "OrderNo": string,
    "OrderDate": string,
    "OrderType": number,
    "Body": string,
    "TradeNo": string,
    "PayType": number,
    "TotalFee": number,
    "PayState": number,//支付状态:1未支付,2已支付3已退费 4部分退款 5已取消  6退款中
    "AccountNo": string,
    "Memo": string,
    "PayDate": string,
    "TransactionId": string,
    "MchId": string,
    "BankType": string,
    "TimeEnd": string,
    "WorkId": number,
    "PayScene": number
}

class Pay_Order_ORM {
    public data = {
        dbConn: TSLobsterAPI.Program.GetDbConn(),
        WorkId: 1
    }

    constructor(workid: number) {
        this.data.WorkId = workid;

        this.Pay_Order.WorkId = workid;
    }

    public Pay_Order = {
        "model": {
            "ID": 0,
            "SubMchId": "",
            "BusinessOrderNo": "",
            "OrderNo": "",
            "OrderDate": "yyyy-MM-dd",
            "OrderType": 0,
            "Body": "",
            "TradeNo": "",
            "PayType": 0,
            "TotalFee": 0,
            "PayState": 0,
            "AccountNo": "",
            "Memo": "",
            "PayDate": "yyyy-MM-dd",
            "TransactionId": "",
            "MchId": "",
            "BankType": "",
            "TimeEnd": "yyyy-MM-dd",
            "WorkId": 0,
            "PayScene": 0
        },
        "tablename": "Pay_Order",
        "key": "ID",
        "val": "0",
        "objval": {},
        "query": {},
        "where": "",
        "pageinfo": {},
        "WorkId": 1
    }

    Save(order: Pay_Order_Model): any {
        this.Pay_Order.objval = order;
        return TSLobsterAPI.DbHelper.SaveModel(this.data.dbConn, this.Pay_Order);
    }

    GetList(where?: string) {
        return TSLobsterAPI.OrmMsSql.GetListModel(this.data.dbConn, this.Pay_Order);
    }
}



/**
 * 收银台服务
 * 
 * 使用收银台步骤：
 * 1、后台新增商户号
 * 2、打开应用订阅服务，订阅支付系统应用(3063)的pay.pay.preorder
 * 3、打开应用发布服务，选择自己应用并创建服务register.tspaynotify.paysuccess(支付成功回调通知)和register.tspaynotify.refundsuccess(退款成功回调通知)
 *      比如：在智慧诊疗应用(3223)中创建了
 *      服务：register.tspaynotify.paysuccess，服务地址：/lowcode/?appid=3223&view=api&fun=tspaynotify.paysuccess
 *      服务：register.tspaynotify.refundsuccess，服务地址：/lowcode/?appid=3223&view=api&fun=tspaynotify.refundsuccess
 * 4、后台新增商户号配置刚刚智慧诊疗应用的服务
 */
class cashworkService {
    public data = {
        dbConn: TSLobsterAPI.Program.GetDbConn(),
        WorkId: 1,
        AppId: 1
    }

    public service: tsfrontService;
    public dao: tsfrontDao;

    constructor(workid: number, appid: number) {
        this.data.WorkId = workid;
        this.data.AppId = appid;

        this.service = new tsfrontService(this.data.WorkId);
        this.dao = new tsfrontDao(this.data.WorkId);

    }

    /**
     * 预下单
     * 参数：model
     * SubMchId: '',//支付商户号
     * BusinessOrderNo: 0,//业务唯一标识
     * OrderType: 1,//业务类型 1预约挂号 2自助缴费
     * PayType: 1,//默认1 微信支付
     * PayScene: 1,//1 h5 2小程序 3app
     * Price: 0, //单位分
     * Body: '预约挂号',//商品描述
     * Memo: '备注'//可以不填
     * 
     * 返回：
     * pay.html 收银台页面
     */
    preorder(model) {

        if (this.checkordertype(model.OrderType) == false) {
            throw '订单类型不正确';
        }

        if (this.checkpayscene(model.PayScene) == false) {
            throw '支付场景不正确';
        }

        // var mch = this.dao.getMch(model.SubMchId);
        var payment = this.dao.getPayment(model.SubMchId, model.PayType);
        var order = this.dao.getOrder(model.SubMchId, model.BusinessOrderNo);

        let payredirecturl;
        let payOrderNo;

        if (order && order.ID > 0) {
            if (order.PayState == 2) {
                throw '该订单已已支付';
            }

            payOrderNo = order.OrderNo;

        } else {
            var orderNo = this.service.generateTimeReqestNumber();

            let payorder = new Pay_Order_ORM(this.data.WorkId);
            var orderVal: Pay_Order_Model = <Pay_Order_Model>{};
            orderVal.SubMchId = model.SubMchId;
            orderVal.BusinessOrderNo = model.BusinessOrderNo;
            orderVal.OrderNo = orderNo;
            orderVal.OrderDate = TSLobsterAPI.Utils.getCurrTime(null);
            orderVal.OrderType = model.OrderType;
            orderVal.TradeNo = "";
            orderVal.Body = model.Body;
            orderVal.PayType = model.PayType;
            orderVal.TotalFee = model.Price / 100;
            orderVal.PayState = 1;
            orderVal.AccountNo = "";
            orderVal.Memo = model.Memo;
            orderVal.MchId = payment.MchId;
            orderVal.WorkId = this.data.WorkId;
            orderVal.PayScene = model.PayScene;
            payorder.Save(orderVal);

            payOrderNo = orderNo;
        }

        if (model.PayScene == 1) {
            payredirecturl = "/weuiapp/" + this.data.AppId + "/pay.html?payOrderNo=" + payOrderNo;
        } else if (model.PayScene == 2) {
            //?
        } else if (model.PayScene == 3) {
            //?
        }

        return { payredirecturl: payredirecturl };
    }
    /**
     * 检查订单类型是否存在
     */
    checkordertype(ordertype: any): boolean {
        //获取订单类型
        var dict = TSLobsterAPI.AppFunction.GetAppBaseDict(this.data.AppId, "8329");
        // TSLobsterAPI.Utils.TrackLog('dict',dict);
        // TSLobsterAPI.Utils.TrackLog('ordertype',ordertype);
        // TSLobsterAPI.Utils.TrackLog('map',dict.map(x => { return x.Code; }));
        if (dict.map(x => { return parseInt(x.Code); }).indexOf(ordertype) > -1) {
            return true;
        }

        return false;
    }

    /**
     * 检查支付场景是否为
     * 1 h5 2小程序 3app
     */
    checkpayscene(payscene: any): boolean {
        if (payscene == 1) {//h5
            return true;
        }
        else if (payscene == 2)//小程序
        {
            return true;
        }
        else if (payscene == 3)//app
        {
            return true;
        }

        return false;
    }
}

/**
 * 微信支付服务
 * 
 * 支付设计思路
 * 1、外部系统先调用预下单接口preorder，返回收银台页面pay.html
 * 2、调起支付接口unifiedorder，然后调用/pay/v1/Pay/Unifiedorder，等待支付成功
 * 3、微信支付成功后回调通知接口payNotify
 * 4、收到微信回调通知后调用外部系统的支付成功回调地址，调用成功收银台显示支付成功
 * 
 * Pay_Order表的字段说明
 * 1、BusinessOrderNo：业务订单号，由外部系统传入，预支付接口写入
 * 2、OrderNo：订单号，由支付系统生成，预支付接口写入
 * 3、TradeNo：交易流水号，还不知道谁生成的，什么时候生成的?
 * 4、TransactionId：第三方支付流水号，由微信生成，支付成功后回调通知接口写入
 * 
 * 退款设计思路
 * 1、外部系统申请退款调用接口refund，然后调用/pay/v1/Pay/Refund
 * 2、微信退款成功后回调通知接口refundNotify
 * 3、收到微信回调通知后调用外部系统的退款成功回调地址，调用成功显示退款成功
 */
class weixinpayService {

    public data = {
        dbConn: TSLobsterAPI.Program.GetDbConn(),
        WorkId: 1,
        AppId: 1
    }

    public service: tsfrontService;
    public dao: tsfrontDao;

    constructor(workid: number, appid: number) {
        this.data.WorkId = workid;
        this.data.AppId = appid;

        this.service = new tsfrontService(this.data.WorkId);
        this.dao = new tsfrontDao(this.data.WorkId);

    }

    /**
     * 调用微信支付
     * 参数：
     * orderNo: self.data.payOrderNo,
     * payType: payType
     * openid: self.data.openid, //微信openid
     */
    unifiedorder(model) {
        try {

            var order = this.dao.getOrderByNo(model.orderNo);
            if (!order.ID) {
                throw '订单不存在';
            }
            if (order.PayState == 2) {
                throw '已支付';
            }
            if (order.PayState == 5) {
                throw '已关闭';
            }

            var payment = this.dao.getPayment(order.SubMchId, model.payType);

            //更改了支付方式
            if (model.payType != order.PayType) {
                this.dao.updateOrderPayType(model.orderNo, model.payType);
            }

            if (model.payType == 3) {//判断余额
                throw '暂未开通';
            }

            //微信支付
            if (model.payType == 1) {
                var payobject = {
                    AppID: payment.AppID,
                    MchId: payment.MchId,
                    ApiKey: payment.ApiKey,
                    NotifyUrl: payment.NotifyUrl,
                    openid: model.openid,
                    Body: order.Body,
                    OrderNo: order.OrderNo,
                    PayType: model.payType,
                    PayScene: order.PayScene,
                    Price: order.TotalFee * 100,
                    ClientIP: '127.0.0.1',
                    SubMchId: order.SubMchId,
                }
                var res = TSLobsterAPI.Http.Post('/pay/v1/Pay/Unifiedorder', payobject);
                return res["data"];
            } else if (model.payType == 2) {
                throw '暂未开通';
            } else if (model.payType == 3) {
                //直接更新订单状态
                throw '暂未开通';
            } else {
                throw '支付方式错误';
            }
        } catch (e) {
            throw e;
        }
    }

    /**
     * 微信支付成功后回调通知接口
     * {
            subMchId = subMchId,  //支付接口传入的商户号
            orderNo = outTradeNo, //支付接口传入的订单号
            transactionId = tradeNo, //微信支付订单号
            totalFee = totalFee, //金额 单位：分
            bankType = bankType,  //付款银行
            timeEnd = timeEnd,
            attach = attach,
            mchId = mchId //微信商户号
        }
     */
    payNotify(model) {
        try {

            var order = this.dao.getOrderByNo(model.orderNo);

            if (order && order.PayState == 2) {
                return { result: true };
            }
            else if (order && order.ID > 0) {
                let strsql = "update pay_order set PayState=2,PayDate=getdate(),TransactionId=@transactionId,BankType=@bankType,TimeEnd=@timeEnd where ID=@ID";
                let dbparams = {
                    ID: order.ID,
                    transactionId: model.transactionId,
                    bankType: model.bankType,
                    timeEnd: TSLobsterAPI.Utils.dateFormat(new Date(model.timeEnd))
                }
                TSLobsterAPI.DbHelper.DbExecuteUpdate(this.data.dbConn, strsql, dbparams);

                if (order.BusinessOrderNo > 0) {
                    //回写外部应用的状态
                    var postmodel = {
                        OrderType: order.OrderType,
                        OrderNo: order.OrderNo,
                        TransactionId: model.transactionId,
                        BusinessOrderNo: order.BusinessOrderNo,
                        SubMchId: order.SubMchId,
                        PayDate: order.PayDate,
                        PayType: order.PayType,
                        PayFee: model.totalFee
                    }
                    var payment = this.dao.getPayment(order.SubMchId, order.PayType);
                    TSLobsterAPI.Utils.TrackLog("payment", payment);
                    TSLobsterAPI.Utils.TrackLog("postmodel", postmodel);
                    // MirthAPI.AppFunction.PublishCAP("pay.pay.paysuccess", postmodel);
                    var res = TSLobsterAPI.AppFunction.CallOutService(this.data.AppId, payment.BusinessNotifyUrl, postmodel);
                    TSLobsterAPI.Utils.TrackLog(payment.BusinessNotifyUrl, res);
                }
                return { result: true };
            }
        } catch (e) {
            throw e;
        }
    }

    /**
     * 关闭订单
     * {
            SubMchId: '20220505085609644323',
            BusinessOrderNo: "67"
        }
     */
    closeorder(model) {
        try {

            var order = this.dao.getOrder(model.SubMchId, model.BusinessOrderNo);
            if (!order.ID) {
                throw '订单不存在';
            }
            if (order.PayState == 2) {
                throw '已支付不能关闭';
            }
            var payment = this.dao.getPayment(order.SubMchId, order.PayType);
            var closeorderobject = {
                AppID: payment.AppID,
                MchId: payment.MchId,
                OrderNo: order.OrderNo,
                PayType: order.PayType,
                ApiKey: payment.ApiKey
            }

            var res = TSLobsterAPI.Http.Post('/Pay/v1/Pay/CloseOrder', closeorderobject);

            if (res['code'] == 0) {
                let strsql = "update pay_order set paystate=5 where orderno=@OrderNo";
                TSLobsterAPI.DbHelper.DbExecuteUpdate(this.data.dbConn, strsql, { OrderNo: order.OrderNo });
            } else {
                throw '关闭订单失败'
            }

            return {result:true};
        } catch (e) {
            throw e;
        }
    }

    /**
     * 调用微信退款
     * {
            SubMchId: '20220505085609644323',
            BusinessOrderNo: "67",                          //业务唯一标识，由外部应用传入
            BusinessRefundNo: "123",                        //退款业务唯一标识，由外部应用传入
            PayType: 1,                                     //默认1 微信支付
            RefundRealFee: 1,                               //金额 单位分
            RefundDesc: '预约挂号退款',                      //商品描述 
        }
     */
    refund(model) {
        try {
            TSLobsterAPI.Utils.TrackLog("退款处理", model);

            var order = this.dao.getOrder(model.SubMchId, model.BusinessOrderNo);
            if (!order) {
                throw '订单不存在';
            }

            // var mch = this.dao.getMch(model.SubMchId);
            var payment = this.dao.getPayment(order.SubMchId, order.PayType);
            var refundOrder = this.dao.getRefundOrder(model.SubMchId, model.BusinessRefundNo);
            var refundNo = "R" + this.service.generateTimeReqestNumber();//生成退款订单号
            if (!refundOrder) {

                //更新订单状态为6退款中
                let strsql = "update Pay_Order set PayState=6 where ID=@ID";
                TSLobsterAPI.DbHelper.DbExecuteUpdate(this.data.dbConn, strsql, { ID: order.ID });

                //插入退款订单
                strsql = "INSERT INTO  Pay_RefundOrder (SubMchId ,OrderNo ,BusinessOrderNo  ,RefundDate ,RefundFee ,SettlementRefundFee\
                            ,RefundNo ,BusinessRefundNo ,RefundStatus ,RefundDesc,WorkId)\
                            VALUES  (@SubMchId,@OrderNo,@BusinessOrderNo,getdate(),@RefundFee,@SettlementRefundFee,@RefundNo,@BusinessRefundNo,@RefundStatus,@RefundDesc,@WorkId)";
                let dbparams = {
                    SubMchId: model.SubMchId,
                    OrderNo: order.OrderNo,
                    BusinessOrderNo: order.BusinessOrderNo,
                    RefundFee: parseInt(model.RefundRealFee) / 100,
                    SettlementRefundFee: parseInt(model.RefundRealFee) / 100,
                    RefundNo: refundNo,
                    BusinessRefundNo: model.BusinessRefundNo,
                    RefundStatus: 0,
                    RefundDesc: model.RefundDesc,
                    WorkId: this.data.WorkId
                }
                TSLobsterAPI.DbHelper.DbExecuteUpdate(this.data.dbConn, strsql, dbparams);
            }

            if (order.PayType == 1) {
                //发起微信退款
                var refundobject = {
                    AppID: payment.AppID,
                    MchId: payment.MchId,
                    ApiKey: payment.ApiKey,
                    RefundNotifyUrl: payment.RefundNotifyUrl,
                    SubMchId: payment.SubMchId,
                    OrderNo: order.OrderNo,
                    RefundNo: refundNo,
                    PayFee: order.TotalFee * 100,
                    RefundRealFee: model.RefundRealFee,
                    RefundDesc: model.RefundDesc,
                }
                // MirthAPI.TrackLog("调用退款接口参数Refund", refundobject);
                var res = TSLobsterAPI.Http.Post('/pay/v1/Pay/Refund', refundobject);
                // MirthAPI.TrackLog("调用退款接口返回值Refund", res);
                return res['data'];
            } else if (order.PayType == 2) {
                throw '暂未开通';
            } else if (order.PayType == 3) {
                throw '暂未开通';
            } else {
                throw '支付方式错误';
            }

        } catch (e) {

            throw e;
        }
    }

    /**
     * 微信退款成功后回调通知接口
     * {
     *      OrderNo = outTradeNo,               //退款接口传入的原始订单号
            RefundNo = outRefundNo,             //退款接口传入的退款订单号 
            TransactionId = transaction_id,     //退款交易号
            RefundFee = refund_fee,
            TotalFee = total_fee,
            RefundStatus = refundStatus,        //1退款成功 2退款异常 3退款关闭
            SuccessTime = successTime,
            RefundId = refund_id,
            MchId = mch_id
        }
     */
    refundNotify(model) {
        try {

            var refundorder = this.dao.getRefundOrderByNo(model.RefundNo);
            if (parseInt(refundorder['ID']) > 0) {
                //更新状态
                let strsql = "update Pay_RefundOrder set RefundStatus=@RefundStatus,SuccessTime=@SuccessTime,TransactionId=@TransactionId,RefundId=@RefundId where ID=@ID";
                let dbparams = {
                    ID: refundorder.ID,
                    RefundStatus: model.RefundStatus,
                    SuccessTime: model.SuccessTime,
                    TransactionId: model.TransactionId,
                    RefundId: model.RefundId
                }
                TSLobsterAPI.DbHelper.DbExecuteUpdate(this.data.dbConn, strsql, dbparams);

                var refundorderlist = this.dao.getRefundOrderListByNo(model.OrderNo);
                var order = this.dao.getOrderByNo(model.OrderNo);
                if (order.ID > 0) {
                    var refundFee = 0;
                    var paystate = 0;
                    refundorderlist.forEach(item => {
                        refundFee += item.RefundFee
                    });
                    if (refundFee * 100 + model.RefundFee < model.TotalFee)
                        paystate = 4;
                    else
                        paystate = 3

                    let strsql = "update Pay_Order set PayState=@PayState where ID=@ID";
                    TSLobsterAPI.DbHelper.DbExecuteUpdate(this.data.dbConn, strsql, { ID: order.ID, PayState: paystate });

                }

                if (refundorder.BusinessOrderNo > 0) {
                    //回写外部应用的状态
                    let backrefundobj = {
                        OrderType: order.OrderType,                              //1挂号支付 2处方支付
                        OrderNo: order.OrderNo || '',                            //支付系统生成的订单号
                        TransactionId: order.TransactionId || '',                //微信支付生成的唯一号
                        BusinessOrderNo: order.BusinessOrderNo || 0,             //业务号，对应WPMT_RegisteredPayment和WPMT_PresPayment表的主键
                        RefundNo: refundorder.RefundNo || '',                           //退款订单号
                        RefundTransactionId: model.TransactionId || '',     //退款交易流水号
                        SubMchId: order.SubMchId,                                //商户号
                        PayType: order.PayType,                                  //支付方式 1微信 2医保 3其它
                        RefundDate: model.SuccessTime,                            //支付时间
                        RefundFee: model.RefundFee            //支付金额 到分
                    }
                    var payment = this.dao.getPayment(order.SubMchId, order.PayType);
                    var res = TSLobsterAPI.AppFunction.CallOutService(this.data.AppId, payment.BusinessRefundNotifyUrl, backrefundobj);
                    TSLobsterAPI.Utils.TrackLog(payment.BusinessNotifyUrl, res);
                    return { result: true };
                }

            }
        } catch (e) {
            throw e;
        }
    }
}